/**
 * Copyright 2025 NoEvaa
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <iostream>
#include <random>

#include "aymmap/aymmap.hpp"

using namespace aymmap;

void printFile(MMapFileStream & mmfs) {
    char c;
    std::cout << "File data: ";
    while (mmfs.buffer().readByte(c)) {
        std::cout << (int)c << ' ';
    }
    std::cout << std::endl;
    mmfs.buffer().seek(0, BufferPos::kBeg);
}

template <typename... Ts>
struct FillWrapper {
    void operator()(MMapFileStream & mmfs) {
        (Ts{}(mmfs), ...);
    }
};

struct FillZero {
    void operator()(MMapFileStream & mmfs) {
        mmfs.fill(0);
        std::cout << ">> fill zero" << std::endl;
        printFile(mmfs);
    }
};

struct FillRand {
    void operator()(MMapFileStream & mmfs) {
        std::mt19937 gen(std::random_device{}());
        std::uniform_int_distribution<uint32_t> idist(0, 0xffffffff);
        auto fn_rand = [&]() -> int { return idist(gen); };
        mmfs.fill(fn_rand);
        std::cout << ">> fill rand" << std::endl;
        printFile(mmfs);
    }
};

using FillDefault3 = FillWrapper<FillZero, FillRand, FillZero>;

template <typename... Ts>
void shred(fs::path const & ph) {
    MMapFileStream mmfs;
    if (mmfs.map(ph, AccessFlag::kReadWrite)) {
        assert(0);
        return;
    }
    FillWrapper<Ts...>{}(mmfs);
    fs::remove(ph);
}

int main() {
    {
        MMapFileStream mmfs;
        mmfs.map("test.txt", AccessFlag::kDefault, 10);
        for (char c = 0; c < 10; ++c) {
            mmfs.writeByte(c);
        }
        mmfs.buffer().seek(0, BufferPos::kBeg);
        printFile(mmfs);
    }
    shred<FillDefault3>("test.txt");
    return 0;
}

